/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

import { expect } from '@jest/globals';
import * as fse from 'fs-extra';
import * as path from 'path';

import { initByStageEmptyApp, initByStageEmptyService, initExecuteCommand, runHvigor } from './common/common';
import { ModuleBuildProfileModifier } from './common/modifier/module-build-profile-modifier';

describe('build hap signing test', () => {
  test.concurrent('test stage app package entry hap not signing', async () => {
    await initByStageEmptyApp(async (projectRoot) => {
      const commands = initExecuteCommand({
        mode: 'module',
        product: 'default',
        tasks: 'assembleHap'
      });
      await testHapSignFalse(projectRoot, commands);
    }, { sign: false });
  });

  test.concurrent('test stage app package entry hap signing', async () => {
    await initByStageEmptyApp(async (projectRoot) => {
      const commands = initExecuteCommand({
        mode: 'module',
        product: 'default',
        tasks: 'assembleHap'
      });
      await testHapSignTrue(projectRoot, commands);
    }, { sign: true });
  });

  test.concurrent('test stage app package feature hap not signing', async () => {
    await initByStageEmptyApp(async (projectRoot) => {
      const commands = initExecuteCommand({
        mode: 'module',
        product: 'default',
        module: 'feature@default',
        tasks: 'assembleHap'
      });
      await testHapSignFalse(projectRoot, commands, 'feature');
    }, { sign: false });
  });

  test.concurrent('test stage app package feature hap signing', async () => {
    await initByStageEmptyApp(async (projectRoot) => {
      const commands = initExecuteCommand({
        mode: 'module',
        product: 'default',
        module: 'feature@default',
        tasks: 'assembleHap'
      });
      await testHapSignTrue(projectRoot, commands, 'feature');
    }, { sign: true });
  });

  test.concurrent('test stage service package entry hap not signing', async () => {
    await initByStageEmptyService(async (projectRoot) => {
      const commands = initExecuteCommand({
        mode: 'module',
        product: 'default',
        module: 'entry@default',
        tasks: 'assembleHap'
      });
      testHapServiceSignFalse(projectRoot, commands, 'entry');
    }, { sign: false });
  });

  test.concurrent('test stage service package feature hap not signing', async () => {
    await initByStageEmptyService(async (projectRoot) => {
      const commands = initExecuteCommand({
        mode: 'module',
        product: 'default',
        module: 'feature@default',
        tasks: 'assembleHap'
      });
      testHapServiceSignFalse(projectRoot, commands, 'feature');
    }, { sign: false });
  });
});

export async function testHapServiceSignFalse(projectRoot: string, commands: string[], moduleName: string) {
  new ModuleBuildProfileModifier(projectRoot, 'entry').updateTargetRuntimeOS('default', 'OpenHarmony');
  new ModuleBuildProfileModifier(projectRoot, 'feature').updateTargetRuntimeOS('default', 'OpenHarmony');
  new ModuleBuildProfileModifier(projectRoot, 'slibrary').updateTargetRuntimeOS('default', 'OpenHarmony');
  const result = runHvigor(projectRoot, commands);
  expect(result.stderr).toContain('Atomic service development is not supported in the OpenHarmony stage model.');
  new ModuleBuildProfileModifier(projectRoot, 'entry').updateTargetRuntimeOS('default', 'HarmonyOS');
  new ModuleBuildProfileModifier(projectRoot, 'feature').updateTargetRuntimeOS('default', 'HarmonyOS');
  new ModuleBuildProfileModifier(projectRoot, 'slibrary').updateTargetRuntimeOS('default', 'HarmonyOS');

  const modifyRuntimeOSResult = runHvigor(projectRoot, commands);
  const moduleStr = `${moduleName}:default`;
  expect(modifyRuntimeOSResult.stderr)
    .toContain('Will skip sign \'hos_hap\'. No signingConfigs profile is configured in current project');
  expect(modifyRuntimeOSResult.stdout).toContain(`Finished :${moduleStr}@SignHap`);
  expect(modifyRuntimeOSResult.stdout).toContain('BUILD SUCCESSFUL');

  const warnResult = runHvigor(projectRoot, commands);
  expect(warnResult.stderr)
    .toContain('Will skip sign \'hos_hap\'. No signingConfigs profile is configured in current project');
  expect(warnResult.stdout).toContain(`Finished :${moduleStr}@SignHap`);
  expect(warnResult.stdout).toContain('BUILD SUCCESSFUL');

  const output = path.resolve(projectRoot, 'feature/build/default/outputs');
  await fse.removeSync(output);
  const result3 = runHvigor(projectRoot, commands);
  expect(result3.stderr)
    .toContain('Will skip sign \'hos_hap\'. No signingConfigs profile is configured in current project');
  expect(result3.stdout).toContain(`Finished :${moduleStr}@SignHap`);
  expect(result3.stdout).toContain('BUILD SUCCESSFUL');
}

export async function testHapSignFalse(projectRoot: string, commands: string[], module?: string) {
  const result = runHvigor(projectRoot, commands);
  let moduleStr = 'entry:default';
  if (module === 'feature') {
    moduleStr = 'feature:default';
  }

  expect(result.stderr)
    .toContain('Will skip sign \'hos_hap\'. No signingConfigs profile is configured in current project');

  expect(result.stdout).toContain(`Finished :${moduleStr}@SignHap`);
  expect(result.stdout).toContain('BUILD SUCCESSFUL');
  const result2 = runHvigor(projectRoot, commands);
  expect(result2.stderr)
    .toContain('Will skip sign \'hos_hap\'. No signingConfigs profile is configured in current project');
  expect(result2.stdout).toContain(`Finished :${moduleStr}@SignHap`);
  expect(result2.stdout).toContain('BUILD SUCCESSFUL');
  const output = path.resolve(projectRoot, `${module === 'feature' ? 'feature' : 'entry'}/build/default/outputs`);
  await fse.removeSync(output);
  const result3 = runHvigor(projectRoot, commands);
  expect(result3.stderr)
    .toContain('Will skip sign \'hos_hap\'. No signingConfigs profile is configured in current project');
  expect(result3.stdout).toContain(`Finished :${moduleStr}@SignHap`);
  expect(result3.stdout).toContain('BUILD SUCCESSFUL');
}

export async function testHapSignTrue(projectRoot: string, commands: string[], module?: string) {
  const result = runHvigor(projectRoot, commands);

  // Api8 涉及SignShell任务时不支持增量
  if (result.stdout.includes('SignShell')) {
    expect(result.stdout).toContain('Finished ::SignApp');
    return;
  }

  let moduleStr = 'entry:default';
  if (module === 'feature') {
    moduleStr = 'feature:default';
  }

  expect(result.stdout).toContain(`Finished :${moduleStr}@SignHap`);
  expect(result.stdout).toContain('BUILD SUCCESSFUL');
  const result2 = runHvigor(projectRoot, commands);
  expect(result2.stdout).toContain(`UP-TO-DATE :${moduleStr}@SignHap`);
  expect(result2.stdout).toContain('BUILD SUCCESSFUL');
  const output = path.resolve(projectRoot, `${module === 'feature' ? 'feature' : 'entry'}/build/default/outputs`);
  await fse.removeSync(output);
  const result3 = runHvigor(projectRoot, commands);
  expect(result3.stdout).toContain(`Finished :${moduleStr}@SignHap`);
  expect(result3.stdout).toContain('BUILD SUCCESSFUL');
}
